package com.wx.service;

import com.google.common.collect.Lists;
import com.wx.common.SecurityUser;
import com.wx.constants.Constants;
import com.wx.domain.vo.AddressDataVo;
import com.wx.domain.vo.AddressTreeVo;
import com.wx.entity.SysAddress;
import com.wx.exception.BusinessException;
import com.wx.mapper.SysAddressMapper;
import com.wx.service.impl.BaseServiceImpl;
import com.wx.utils.SnowFlakeUtil;
import com.wx.utils.TreeUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>Title:      SysAddressServiceImpl. </p>
 * <p>Description 省市区地址编码 </p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company:    医百科技有限公司 </p>
 *
 * @author         <a href="yangwensheng@100doc.com.cn"/>杨文生</a>
 * @since      2022/4/16 10:21
 */
@Service
@CacheConfig(cacheNames = "weixin:go:weith:you:address")
public class SysAddressServiceImpl extends BaseServiceImpl<SysAddress> implements SysAddressService {

    @Resource
    private SysAddressMapper sysAddressMapper;

    @Override
    public List<SysAddress> getChildrenByParentCode(String parentCode) {
        return sysAddressMapper.getChildrenByParentCode(parentCode);
    }

    @Override
    @Cacheable(unless="#result == null", cacheNames = {"all"})
    public List<SysAddress> getAll() {
        return sysAddressMapper.getAll();
    }

    @Override
    public int insert(SysAddress sysAddress, SecurityUser authUserDto) {
        sysAddress.setDelFlag(Constants.DELETE_NO);
        List<SysAddress> count = sysAddressMapper.select(sysAddress);
        if(count.size() > 0) {
            throw new BusinessException("地址编码已经存在，不能重复");
        }
        SysAddress address = sysAddressMapper.queryAddressByCode(sysAddress.getParentCode());
        if(address == null){
            throw new BusinessException("查询父节点信息不存在");
        }
        sysAddress.setLevel(address.getLevel() + 1);
        sysAddress.setId(SnowFlakeUtil.getStringId());
        return sysAddressMapper.insertSelective(sysAddress);
    }


    @Override
    public int updateInfo(SysAddress sysAddress, SecurityUser authUserDto) {
        SysAddress address = sysAddressMapper.selectByPrimaryKey(sysAddress.getId());
        if(address == null){
            throw new BusinessException("参数不合法");
        }
        SysAddress parentAddress = sysAddressMapper.queryAddressByCode(sysAddress.getParentCode());
        if(parentAddress == null){
            throw new BusinessException("查询父节点信息不存在");
        }
        if(sysAddress.getParentCode().equals(sysAddress.getCode())){
            throw new BusinessException("父节点不能选择自己");
        }
        sysAddress.setLevel(parentAddress.getLevel() + 1);
        sysAddress.setUpdateDate(new Date());
        sysAddress.setUpdateBy(authUserDto.getUserId());
        sysAddress.setUpdater(authUserDto.getUsername());
        return sysAddressMapper.updateByPrimaryKeySelective(sysAddress);
    }


    @Override
    public List<AddressTreeVo> treeList() {
        List<SysAddress> sysAddresses = sysAddressMapper.queryProvinceAndCity();
        Map<String, String> dicMap = sysAddresses.stream().collect(Collectors.toMap(SysAddress::getCode, SysAddress::getName));
        List<AddressTreeVo> trees = Lists.newArrayList();
        AddressTreeVo node = null;
        for (SysAddress address : sysAddresses) {
            node = new AddressTreeVo();
            BeanUtils.copyProperties(address, node);
            node.setAreaId(address.getId());
            node.setId(address.getCode());
            node.setAddressName(address.getName());
            node.setParentId(address.getParentCode());
            String parentDicName = dicMap.get(address.getParentCode());
            node.setParentName(parentDicName);
            trees.add(node);
        }
        return TreeUtil.bulid(trees, "root");
    }


    @Override
    @Cacheable(cacheNames = "treeList")
    public List<AddressTreeVo> getAddressTree() {
        List<SysAddress> sysAddresses = sysAddressMapper.getAll();
        Map<String, String> dicMap = sysAddresses.stream().collect(Collectors.toMap(SysAddress::getCode, SysAddress::getName));
        List<AddressTreeVo> trees = Lists.newArrayList();
        AddressTreeVo node = null;
        for (SysAddress address : sysAddresses) {
            node = new AddressTreeVo();
            BeanUtils.copyProperties(address, node);
            node.setAreaId(address.getId());
            node.setId(address.getCode());
            node.setAddressName(address.getName());
            node.setParentId(address.getParentCode());
            String parentDicName = dicMap.get(address.getParentCode());
            node.setParentName(parentDicName);
            trees.add(node);
        }
        return TreeUtil.bulid(trees, Constants.Sys.ROOT_PARENTID);
    }

    @Override
    public int delete(String id) {
        // 校验参数是否合法
        SysAddress address = sysAddressMapper.selectByPrimaryKey(id);
        if(address == null){
            throw new BusinessException("参数不合法");
        }
        // 校验是否包含子节点
        SysAddress query = new SysAddress();
        query.setParentCode(address.getCode());
        query.setDelFlag(Constants.DELETE_NO);
        int count = sysAddressMapper.selectCount(query);
        if(count > 0){
            throw new BusinessException("该节点下还存在子节点，不能将其删除");
        }
        return sysAddressMapper.deleteByPrimaryKey(id);
    }

    @Override
    public AddressDataVo getAddressInfo() {
        List<SysAddress> sysAddresses = sysAddressMapper.getAll();
        List<SysAddress> provinceList = sysAddresses.stream().filter(f -> f.getLevel().equals(Constants.Level.PROVINCE_LEVEL)).collect(Collectors.toList());
        List<SysAddress> cityList = sysAddresses.stream().filter(f -> f.getLevel().equals(Constants.Level.CITY_LEVEL)).collect(Collectors.toList());
        List<SysAddress> areaList = sysAddresses.stream().filter(f -> f.getLevel().equals(Constants.Level.AREA_LEVEL)).collect(Collectors.toList());
        AddressDataVo addressDataVo = new AddressDataVo();
        addressDataVo.setProvinceList(provinceList);
        addressDataVo.setCityList(cityList);
        addressDataVo.setAreaList(areaList);
        return addressDataVo;
    }
}
